﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using A2DFramework.AOPService.Core;
using A2DFramework.EsbService.NativeEsb.Configuration;
using A2DFramework.InstanceService;
using A2DFramework.ValidationService;
using A2DFramework.ContextService;

namespace A2DFramework.EsbService.NativeEsb
{
    public class NativeEsbImpl : IEsb
    {
        public TResult Send<TCmd, TResult>(TCmd cmd)
            where TCmd : EsbRequestWrapper
            where TResult : EsbResponseWrapper
        {
            ValidateCommand(cmd);

            string cmdTypeName = typeof(TCmd).FullName;
            if (!NativeEsbConfiguration.CommandHandlerMappings.ContainsKey(cmdTypeName))
                throw new Exception(string.Format("Command Handler mapping config not found for '{0}'", cmdTypeName));

            Type handlerType = NativeEsbConfiguration.CommandHandlerMappings[cmdTypeName];
            if (!typeof(IRequestHandlerWorker).IsAssignableFrom(handlerType))
                throw new Exception("CommandHandler必须实现接口ICommandHandlerProcessor");

            object o;
            if (!ObjectFactory.IsRegistered(handlerType))
                ObjectFactory.Register(handlerType, handlerType);
            o = ObjectFactory.Resolve(handlerType);
            Type handleCommandType = typeof(TCmd);

            MethodInfo handleCommandMethod = HookHandleMethod(o, handleCommandType);
            if (handleCommandMethod == null)
                throw new Exception(string.Format("没有找到能够处理命令[{0}]的方法", handleCommandType.Name));

            object result=handleCommandMethod.Invoke(o, new object[]{cmd});
            return (TResult)result;
        }

        /// <summary>
        /// 找到能够处理指定命令的Handle函数
        /// </summary>
        /// <param name="o"></param>
        /// <param name="realCommandType"></param>
        /// <returns></returns>
        private static MethodInfo HookHandleMethod(object o, Type realCommandType)
        {
            MethodInfo handleCommandMethod = null;
            foreach (var mi in o.GetType().GetMethods().Where(t => t.Name.Equals("Handle")))
            {
                bool thisMethod = false;
                foreach (var pi in mi.GetParameters())
                {
                    if (pi.ParameterType.Equals(realCommandType))
                    {
                        thisMethod = true;
                        break;
                    }
                }
                if (thisMethod)
                {
                    handleCommandMethod = mi;
                    break;
                }
            }
            return handleCommandMethod;
        }

        public void ValidateCommand(object o)
        {
            List<BrokenRule> errors = o.IsValid();

            if (errors != null && errors.Count > 0)
            {
                CoreContext.Current.BrokenRulesContainer.AddBrokenRules(errors);
                throw new Exception(string.Format("命令存在非法参数[{0}]: {1}", o.GetType().Name, CoreContext.Current.BrokenRulesContainer.ToString()));
            }
        }
    }
}
